/**
 * Xml Resource Provider
 * @author Adam Phung
 * 
 * Used to parse XML files.
 * 
 * With help from tutorial at: http://www.drdobbs.com/jvm/easy-dom-parsing-in-java/231002580
 */
package edu.bu.cs673.superkids123.children.model.resources;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.sun.org.apache.xerces.internal.parsers.DOMParser;

import edu.bu.cs673.superkids123.common.model.Achievement;
import edu.bu.cs673.superkids123.common.model.AchievementRule;
import edu.bu.cs673.superkids123.common.model.AchievementRule.Activity;
import edu.bu.cs673.superkids123.common.model.AchievementRule.Compare;
import edu.bu.cs673.superkids123.common.model.AchievementRule.Metric;


public class XmlResourceProvider {
	
	/**
	 * Gets the resource file name from the requested
	 * resource xml.
	 *
	 * @param String key id from ChildrenResource
	 * @param type, Used to pick the correct xml file
	 * @return filePath string to resource
	 */
	public String getResource(String id, ResourceType type) {
		String fileName = null;
		
		try {
			XmlHelper helper = new XmlHelper();
		    DOMParser parser = new DOMParser();
			URL inputFileName = getClass().getResource(type.toString()); 
		    parser.parse(inputFileName.getFile());
		    Document doc = parser.getDocument();
		 
		    // Get the document's root XML node
		    NodeList root = doc.getChildNodes();
		 
		    // Navigate to resourceType node
		    Node resourceType = helper.getNode("resourceType", root);
		    
		    // Get the resource matching the key id
		    Node resource = helper.getNode(id, resourceType.getChildNodes());
		    
		    if (resource == null) {
				// Coudln't find the resource, get the default one.
				if (type != ResourceType.Default) {
					return getResource(id, ResourceType.Default);				
				}
		    }
		    
		    fileName = helper.getNodeValue(resource);
		}
		catch (NullPointerException ex) {
			// NullPointer: Resource key not listed in default.xml
			ex.printStackTrace();
		}
		catch (Exception e) {
		    e.printStackTrace();
		}
		
		return fileName;
	}
	
	public ResourceFormat getResourceFormat(ResourceType type) {
		
		ResourceFormat format = ResourceFormat.Images;
		
		try {
			XmlHelper helper = new XmlHelper();
		    DOMParser parser = new DOMParser();
			URL inputFileName = getClass().getResource(type.toString()); 
		    parser.parse(inputFileName.getFile());
		    Document doc = parser.getDocument();
		 
		    // Get the document's root XML node
		    NodeList root = doc.getChildNodes();
		 
		    // Navigate to resourceType node
		    Node resourceType = helper.getNode("resourceType", root);
		    
		    // Get Node Attribute
		    String formatString = helper.getNodeAttr("format", resourceType);
		    format = ResourceFormat.valueOf(formatString);
		}
		catch (NullPointerException ex) {
			// NullPointer: Resource key not listed in default.xml
			ex.printStackTrace();
		}
		catch (Exception e) {
		    e.printStackTrace();
		}
		
		return format;
	}
	
	public ArrayList<Achievement> getAchievements(String file) {
		ArrayList<Achievement> achievements = new ArrayList<Achievement>();
		
		try {
			XmlHelper helper = new XmlHelper();
		    DOMParser parser = new DOMParser();
			URL inputFileName = getClass().getResource(file); 
		    parser.parse(inputFileName.getFile());
		    Document doc = parser.getDocument();
		 
		    // Get the document's root XML node
		    NodeList root = doc.getChildNodes();
		 
		    // Navigate to achievementList node
		    Node achievementList = helper.getNode("achievementList", root);
		    
		    // Get all achievements from the List node
			for (Node childNode = achievementList.getFirstChild(); childNode != null;) {
				Node nextChild = childNode.getNextSibling();
				
				// parse achievement
				NodeList nodes = childNode.getChildNodes();
				
				if (!helper.getNodeValue("name", nodes).isEmpty()) {
					Achievement a = new Achievement();
					
					a.setName(helper.getNodeValue("name", nodes));
					a.setDescription(helper.getNodeValue("description", nodes));
					a.setPrize(helper.getNodeValue("prize", nodes));
					
					int points = Integer.parseInt(helper.getNodeValue("points", nodes));
					a.setPoints(points);
					
					// rules
					for (AchievementRule rule : getAchievementRules(helper.getNode("ruleList", nodes))) {
						rule.setAchievement(a);
						a.getRules().add(rule);
					}
					
					// add
					achievements.add(a);
				}
				
				childNode = nextChild;
			}
		}
		catch (NullPointerException ex) {
			ex.printStackTrace();
		}
		catch (Exception e) {
		    e.printStackTrace();
		}
		
		return achievements;
	}
	
	private List<AchievementRule> getAchievementRules(Node rulesNode) {
		XmlHelper helper = new XmlHelper();
		List<AchievementRule> rules = new ArrayList<AchievementRule>();
		
		for (Node childNode = rulesNode.getFirstChild(); childNode != null;) {
			Node nextChild = childNode.getNextSibling();
			
			NodeList nodes = childNode.getChildNodes();
			
			if (!helper.getNodeValue("activity", nodes).isEmpty()) {
				AchievementRule rule = new AchievementRule();
				
				rule.setActivity(Activity.valueOf(helper.getNodeValue("activity", nodes)));
				rule.setMetric(Metric.valueOf(helper.getNodeValue("metric", nodes)));
				rule.setComparer(Compare.valueOf(helper.getNodeValue("compare", nodes)));
				rule.setValue(Integer.parseInt(helper.getNodeValue("value", nodes)));
				
				rules.add(rule);
			}
			
			childNode = nextChild;
		}
		
		return rules;
	}
}
